package cn.tedu.hotel.serve.service.impl;

import cn.tedu.hotel.serve.ex.ServiceException;
import cn.tedu.hotel.serve.mapper.UserMapper;
import cn.tedu.hotel.serve.pojo.dto.*;
import cn.tedu.hotel.serve.pojo.entity.User;
import cn.tedu.hotel.serve.pojo.vo.AdminUserVO;
import cn.tedu.hotel.serve.pojo.vo.UserStandardVO;
import cn.tedu.hotel.serve.security.UserForDetails;
import cn.tedu.hotel.serve.service.IUserService;
import cn.tedu.hotel.serve.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class UserServiceImpl implements IUserService {

    @Value("${hotel.serve.jwt.secret-key}")
    String secretKey;

    @Value("${hotel.serve.jwt.duration-in-second}")
    Long durationInSecond;

    @Autowired
    UserMapper userMapper;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    AuthenticationManager authenticationManager;

    @Override
    public void addNew(UserRegisterDTO userRegisterDTO) {
        String username = userRegisterDTO.getUsername();
        int count = userMapper.countByUsername(username);
        if (count > 0) {
            String message = "用户注册失败，用户名已经被注册！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
        }
        count = userMapper.countByPhone(userRegisterDTO.getPhone());
        if (count > 0) {
            String message = "用户注册失败，手机号码已经被注册！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
        }
        User user = new User();
        BeanUtils.copyProperties(userRegisterDTO, user);
        String rawPassword = user.getPassword();
        String encodePassword = passwordEncoder.encode(rawPassword);
        user.setPassword(encodePassword);
        user.setEnable(ENABLE_NUM[1]);
        user.setPermission(PERMISSION);
        count = userMapper.insert(user);
        if (count != 1) {
            String message = "服务器忙请稍后尝试";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_INSERT, message);
        }
    }

    @Override
    public String Login(UserLoginInfoDTO userLoginInfoDTO) {
        log.debug("开始处理【用户登录】的业务，参数：{}", userLoginInfoDTO);
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                userLoginInfoDTO.getUsername(), userLoginInfoDTO.getPassword()
        );
        Authentication authenticateResult = authenticationManager.authenticate(authentication);
        log.debug("认证通过！（如果未通过，过程中将抛出异常，你不会看到此条日志！）");
        log.debug("认证结果：{}", authenticateResult);
        log.debug("认证结果中的当事人：{}", authenticateResult.getPrincipal());
        /*2023-03-17 12:34:34.091 DEBUG 17036 --- [nio-9580-exec-4] c.t.h.s.service.impl.UserServiceImpl     :
        认证结果：UsernamePasswordAuthenticationToken
        [Principal=UserForDetails(super=cn.tedu.hotel.serve.security.UserForDetails
        [Username=user1,
        Password=[PROTECTED],
        Enabled=true,
        AccountNonExpired=true,
        credentialsNonExpired=true,
        AccountNonLocked=true,
        Granted Authorities=[userRoot]],
        id=7),
        Credentials=[PROTECTED],
        Authenticated=true,
        Details=null,
        Granted Authorities=[userRoot]]
         */
        /*SecurityContext securityContext = SecurityContextHolder.getContext();
        securityContext.setAuthentication(authenticateResult);*/
        UserForDetails userForDetails = (UserForDetails) authenticateResult.getPrincipal();
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", userForDetails.getId());
        claims.put("username", userForDetails.getUsername());
        claims.put("nickname", userForDetails.getNickname());
        String authoritiesJsonString = JSON.toJSONString(userForDetails.getAuthorities());
        claims.put("authoritiesJsonString", authoritiesJsonString);

        String jwt = Jwts.builder()
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + durationInSecond * 1000))
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
        log.debug("生成了JWT数据：{}", jwt);
        return jwt;
    }

    @Override
    public void updateInfoById(Long id, UserUpdateDTO userUpdateDTO) {
        UserStandardVO queryResult = userMapper.getStandardById(id);
        // 判断查询结果是否为null
        if (queryResult == null) {
            // 是：抛出异常
            String message = "修改用户详情失败，尝试修改的用户数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        User user = new User();
        BeanUtils.copyProperties(userUpdateDTO, user);
        user.setId(id);
        int rows = userMapper.userUpdate(user);
        if (rows!=1){
            String message = "服务器忙请稍后尝试";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_UPDATE, message);
        }

    }

    @Override
    public void updateUserPassword(Long id, UserUpdatePasswordDTO userUpdatePasswordDTO) {
        UserStandardVO query = userMapper.getStandardById(id);
        // 判断查询结果是否为null
        if (query == null) {
            // 是：抛出异常
            String message = "修改用户详情失败，尝试修改的用户数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        //oldPassword1是从数据库获取,已加密
        String oldPassword1 = query.getPassword();
        //oldPassword2未加密
        String oldPassword2 = userUpdatePasswordDTO.getOldPassword();

        boolean matches = passwordEncoder.matches(oldPassword2, oldPassword1);

        if (!matches) {
            // 是：抛出异常
            String message = "原密码错误！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_BAD_REQUEST, message);
        }
        User user = new User();
        user.setId(id);
        String encodePassword = passwordEncoder.encode(userUpdatePasswordDTO.getNewPassword());
        user.setPassword(encodePassword);

        int rows = userMapper.updateUserPassword(user);
        if (rows!=1){
            String message = "服务器忙请稍后尝试";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_UPDATE, message);
        }

    }

    @Override
    public UserStandardVO getStandardById(Long id) {
        UserStandardVO queryResult = userMapper.getStandardById(id);
        if (queryResult == null) {
            // 是：抛出异常
            String message = "查询相册详情失败，用户数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        return queryResult;
    }

    @Override
    public List<AdminUserVO> getAdminUserVOList() {
        List<AdminUserVO> queryResult = userMapper.getAdminUserVOList();
        if (queryResult == null) {
            // 是：抛出异常
            String message = "查询用户列表失败，用户数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        return queryResult;
    }

    @Override
    public int count() {
        log.debug("开始处理【测试业务，测试用户数量】的业务");
        return userMapper.count();
    }

    @Override
    public void setEnable(Long id) {
        updateEnableById(id, 1);
    }

    @Override
    public void setDisable(Long id) {
        updateEnableById(id, 0);
    }

    private void updateEnableById(Long id, Integer enable) {
        log.debug("开始处理【{}管理员】的业务，ID：{}，目标状态：{}", ENABLE_NUM[enable], id, enable);
        // 不允许调整1号管理员的启用状态
        AdminUserVO adminUserVO = userMapper.getAdminUserVOById(id);

        if ("adminRoot".equals(adminUserVO.getPermission())) {
            String message = "您没有权限，修改失败";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }

        // 检查数据是否存在

        if (adminUserVO == null) {
            String message = ENABLE_NUM[enable] + "管理员失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }

        // 检查当前状态是否与参数表示的状态相同
        if (adminUserVO.getEnable().equals(enable)) {
            String message = ENABLE_NUM[enable] + "管理员失败，当前管理员已经处于"
                    + ENABLE_NUM[enable] + "状态！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
        }

        // 准备执行更新
        User user = new User();
        user.setId(id);
        user.setEnable(enable);
        log.debug("即将修改数据，参数：{}", user);
        int rows = userMapper.adminUpdateUser(user);
        if (rows != 1) {
            String message = ENABLE_NUM[enable] + "管理员失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_UPDATE, message);
        }
    }

    @Override
    public void adminUpdateUser(Long userId, AdminUserDTO adminUserDTO) {
        UserStandardVO result = userMapper.getStandardById(userId);

        log.debug("根据ID={}检查用户数据是否存在，查询结果：{}", userId, result);
        //判断是否存在
        if (result == null) {
            //是,抛出异常
            String message = "修改用户失败，尝试修改的酒店数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        // 调用Mapper对象的update()方法执行修改
        log.debug("即将执行修改，参数：{},{}", userId, adminUserDTO);

        User user = new User();
        BeanUtils.copyProperties(adminUserDTO, user);
        String password = user.getPassword();
        String resultPassword = result.getPassword();
        boolean matchesResult = password.equals(resultPassword);
        if (!matchesResult) {
            String newPasswordEncode = passwordEncoder.encode(password);
            user.setPassword(newPasswordEncode);
        }


        user.setId(userId);
        userMapper.adminUpdateUser(user);

    }

    @Override
    public AdminUserVO getAdminUserVOById(Long id) {

        AdminUserVO queryResult = userMapper.getAdminUserVOById(id);
        if (queryResult == null) {
            // 是：抛出异常
            String message = "查询详情失败，用户数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        return queryResult;
    }

    @Override
    public void deleteById(Long id) {
        log.debug("开始处理【根据id删除管理员】的业务，参数：{}", id);
        // 检查尝试删除的是否为1号管理员
        if (id == 1) {
            String message = "删除管理员失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }

        // 检查尝试删除的数据是否存在
        Object queryResult = userMapper.getStandardById(id);
        if (queryResult == null) {
            String message = "删除管理员失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }

        // 执行删除--管理员表
        log.debug("即将执行删除数据，参数：{}", id);
        int rows = userMapper.deleteById(id);
        if (rows != 1) {
            String message = "删除管理员失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_DELETE, message);
        }

    }
}


